package com.dq.health.security;

import com.dq.health.dto.response.menu.SysMenuTreeInfo;
import com.dq.health.entity.menu.SysMenu;
import com.dq.health.exception.BizExceptionEnum;
import com.dq.health.service.IAPIMenuService;
import com.dq.health.service.IAPIUserService;
import com.dq.health.utils.PrintWriterUtils;
import com.dq.health.utils.data.JsonUtil;
import com.dq.health.utils.data.Tree;
import com.dq.health.utils.view.SimpleView;
import com.dq.health.utils.view.StringView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

@Configuration
public class LoginHandler implements AuthenticationSuccessHandler, AuthenticationFailureHandler {

    private static Logger LOGGER = LoggerFactory.getLogger(LoginHandler.class);

    @Value("${user.password.maxRetryCount:5}")
    private int maxRetryCount;

    private @Autowired IAPIMenuService menuService;
    private @Autowired IAPIUserService sysUserService;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) throws IOException {
        LOGGER.info("登录成功");

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();

        UserDetailsModel detailsModel = (UserDetailsModel)authentication.getPrincipal();

        detailsModel.setSessionId(request.getSession().getId());
        detailsModel.getSysUser().setPassword(null);

        // 获取路由地址
        Long roleId = detailsModel.getSysUser().getRoleId();
        List<SysMenu> sysMenus = menuService.selectMenuListByRoleId(roleId);
        Tree<SysMenuTreeInfo> sysMenuTreeInfoTree = menuService.buildMenus(sysMenus);
        detailsModel.setMenuTreeInfos(sysMenuTreeInfoTree);

        SimpleView<UserDetailsModel> view = new SimpleView<>();
        view.success(detailsModel);
        view.setRspMsg("登录成功");

        out.write(JsonUtil.stringify(view));
        out.flush();
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException exception) {
        LOGGER.info("登录失败");

        StringView resp = new StringView();

        if (exception instanceof UsernameNotFoundException) {
            // UsernameNotFoundException 用户找不到
            resp.fail(BizExceptionEnum.USERNAME_NOT_FOUND.getMsg());
        } else if (exception instanceof BadCredentialsException) {
            // BadCredentialsException 坏的凭据
            // 更新登录失败状态
            resp.fail(BizExceptionEnum.ACCOUNT_NOT_MATCH.getMsg());
            // TODO 设置登陆错误次数锁定
            // String loginName = request.getParameter("username");
            // UserBaseInfo userBaseInfo = sysUserService.queryUserByUserName(loginName);
            // if (userBaseInfo == null) {
            // userBaseInfo = sysUserService.queryUserByMobile(loginName);
            // }
            // if (userBaseInfo != null) {
            // Long userId = userBaseInfo.getUserId();
            // SysUserLoginFail dbSysUserLoginFail = sysUserLoginFailService.getByUserId(userId);
            // SysUserLoginFail updateSysUserLoginFail = new SysUserLoginFail();
            // updateSysUserLoginFail.setUserId(userId);
            // Integer loginFailTimes = dbSysUserLoginFail.getLoginFailTimes();
            // if (loginFailTimes >= (maxRetryCount - 1)) {
            // updateSysUserLoginFail.setStatus(1);
            // } else {
            // updateSysUserLoginFail.setStatus(0);
            // }
            // updateSysUserLoginFail.setLoginFailTimes(loginFailTimes + 1);
            // sysUserLoginFailService.update(updateSysUserLoginFail);
            // }
        } else if (exception instanceof AccountExpiredException) {
            // AccountExpiredException 账户过期
            resp.fail("账户过期");
        } else if (exception instanceof LockedException) {
            // LockedException 账户锁定
            resp.fail(BizExceptionEnum.LOCKED.getMsg());
        } else if (exception.getCause() instanceof LockedException) {
            // LockedException 账户锁定
            resp.fail(BizExceptionEnum.LOCKED.getMsg());
        } else if (exception.getCause() instanceof DisabledException) {
            // DisabledException 账户不可用
            resp.fail(BizExceptionEnum.DISABLED.getMsg());
        } else if (exception instanceof CredentialsExpiredException) {
            // CredentialsExpiredException 证书过期
            resp.fail("凭证已过期");
        } else {
            resp.fail("登录异常，请联系管理员");
            LOGGER.error("登录异常，请联系管理员", exception);
        }

        PrintWriterUtils.flush(response, resp);
    }

}
